﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GoodTrader.GTDownload
{
    public class CpOptionDownloader : CpDownLoader
    {
        public CpOptionDownloader(CpDownLoadManager aDownManager, CpOptionData aData)
            : base(aDownManager)
        {
            mData = aData;
            m_OptChartFetcher.Received += new CPSYSDIBLib._ISysDibEvents_ReceivedEventHandler(OnReceived);
        }

        private string mCode = "";
        public string Code
        {
            get { return mCode; }
            set { mCode = value; }
        }
        
        private short mCycle = 1;
        public short Cycle
        {
            get { return mCycle; }
            set { mCycle = value; }
        }

        private long mStartDate = 0;
        public long StartDate
        {
            get { return mStartDate; }
            set { mStartDate = value; }
        }
        private long mEndDate = 0;
        public long EndDate
        {
            get { return mEndDate; }
            set { mEndDate = value; }
        }

        private double[] arrVal = new double[GTGlobal.MaxDownloadCount];

        private double mEndTime = 0.0;
        private double mOldTime = 0.0;

        // 주간 선물 차트 데이터를 가져오는 객체
        private CPSYSDIBLib.FutOptChartClass m_OptChartFetcher = new CPSYSDIBLib.FutOptChartClass();
        private CpOptionData mData = null; // new CpFutureData();
        public CpOptionData Data
        {
            get { return mData; }
            set { mData = value; }
        }

        public void BlockDownload()
        {
            //object code = m_CpFutureCode.GetData(0, 0);
            if (mCode == "")
                return;

            int[] fields = new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 27, 29 };
            m_OptChartFetcher.SetInputValue(0, mCode);
            m_OptChartFetcher.SetInputValue(1, '2');
            m_OptChartFetcher.SetInputValue(2, mStartDate);
            m_OptChartFetcher.SetInputValue(3, mEndDate);
            m_OptChartFetcher.SetInputValue(4, GTGlobal.MaxDownloadCount);
            m_OptChartFetcher.SetInputValue(5, fields);
            m_OptChartFetcher.SetInputValue(6, 'm');
            m_OptChartFetcher.SetInputValue(7, mCycle);

            // 데이터 수신 요청을 한다.
            try
            {
                // 데이터 수신 요청을 한다.
                m_OptChartFetcher.BlockRequest();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }


            object dataCount = m_OptChartFetcher.GetHeaderValue(3);

            for (int i = Convert.ToInt32(dataCount) - 1, j = 0; i > -1; i--, j++)
            {
                mData.Date[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(0, i)); // 날짜
                mData.Time[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, i)); // 시간
                mData.Open[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(2, i)); // 시가
                mData.High[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(3, i)); // 고가
                mData.Low[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(4, i)); // 저가
                mData.Close[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(5, i)); // 종가
                mData.Amount[j] = Convert.ToDouble(m_OptChartFetcher.GetDataValue(7, i)); // 거래량
            }

            Console.WriteLine("Block Request option : " + mCode + mOldTime.ToString() + "::" + mEndTime.ToString());

            GTGlobal.mEndDate = mData.Date[GTGlobal.MaxDownloadCount - 1];
        }

        // 다운로드 함수로 상속 클래스의 함수를 재정의 한다.
        public override void Download()
        {
            if (mCode == "")
                return;

            // 이미 다운 받은 상태이므로 먼저 베이스 클래스의 함수를 실행한다.
            base.Download();
            // 여기서 다운로드 할 내용을 실행한다.
            //System.Windows.Forms.MessageBox.Show("FutOptDownStarted");

            object code = m_CpFutureCode.GetData(0, 0);
            int[] fields = new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 27, 29 };
            m_OptChartFetcher.SetInputValue(0, code);
            m_OptChartFetcher.SetInputValue(1, '2');
            m_OptChartFetcher.SetInputValue(2, mStartDate);
            m_OptChartFetcher.SetInputValue(3, mEndDate);
            m_OptChartFetcher.SetInputValue(4, 1);
            m_OptChartFetcher.SetInputValue(5, fields);
            m_OptChartFetcher.SetInputValue(6, 'm');
            m_OptChartFetcher.SetInputValue(7, mCycle);

            // 데이터 수신 요청을 한다.
            try
            {
                // 데이터 수신 요청을 한다.
                m_OptChartFetcher.Request();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public override void OnReceived()
        {
            // 베이스 클래스의 함수를 먼저 호출한다. 여기서 이벤트가 다시 설정된다. 
            base.OnReceived();

            if (mData == null)
                return;

            object dataCount = m_OptChartFetcher.GetHeaderValue(3);
            if (Convert.ToInt32(dataCount) <= 0)
                return;

            // 가장 최근 시간을 가져온다.
            mEndTime = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, 0)); // 시간
            double curDate = Convert.ToDouble(m_OptChartFetcher.GetDataValue(0, 0)); // 날짜
            double curTime = Convert.ToDouble(m_OptChartFetcher.GetDataValue(1, 0)); // 시간
            double curOpen = Convert.ToDouble(m_OptChartFetcher.GetDataValue(2, 0)); // 시가
            double curHigh = Convert.ToDouble(m_OptChartFetcher.GetDataValue(3, 0)); // 고가
            double curLow = Convert.ToDouble(m_OptChartFetcher.GetDataValue(4, 0)); // 저가
            double curClose = Convert.ToDouble(m_OptChartFetcher.GetDataValue(5, 0)); // 종가
            double curAmount = Convert.ToDouble(m_OptChartFetcher.GetDataValue(7, 0)); // 거래량

            Console.WriteLine("OnRecieved option : " + mCode + mOldTime.ToString() + "::" + mEndTime.ToString());

            if (mEndTime == mOldTime)
            {
                int endIndex = mData.Time.Length - 1;
                mData.Date[endIndex] = curDate;
                mData.Time[endIndex] = curTime;
                mData.Open[endIndex] = curOpen;
                mData.High[endIndex] = curHigh;
                mData.Low[endIndex] = curLow;
                mData.Close[endIndex] = curClose;
                mData.Amount[endIndex] = curAmount;
            }
            else
            {
                GTGlobal.ShiftArrayVal(curDate, mData.Date, arrVal);
                GTGlobal.ShiftArrayVal(curTime, mData.Time, arrVal);
                GTGlobal.ShiftArrayVal(curOpen, mData.Open, arrVal);
                GTGlobal.ShiftArrayVal(curHigh, mData.High, arrVal);
                GTGlobal.ShiftArrayVal(curLow, mData.Low, arrVal);
                GTGlobal.ShiftArrayVal(curClose, mData.Close, arrVal);
                GTGlobal.ShiftArrayVal(curAmount, mData.Amount, arrVal);
            }
            mOldTime = mEndTime;
        }
    }
}
